package org.springblade.modules.admin.utils;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.google.protobuf.ServiceException;
import org.springblade.core.tool.utils.Func;

import java.text.DecimalFormat;

/**
 * 地图工具类
 * @author Sharry
 */
public class MapUtil {

	/**
	 * 圆周率
	 */
    private final static double PI = 3.14159265358979323;

	/**
	 * 地球的半径
	 */
	private final static double R = 6371229;

	/**
	 * 经度默认格式
	 */
    private final static DecimalFormat DOUBLE_FORMAT = new DecimalFormat("#.000000");

	/**
	 * 附近规定的距离
	 */
    public final static int STIPULATE_DISTANCE = 1000;

    /**
     * 获取坐标距离(米)
     *
     * @param longt1
     *            起始经度
     * @param lat1
     *            起始纬度
     * @param longt2
     *            目地地经度
     * @param lat2
     *            目的地纬度
     * @return
     */
    public static int getDistance(double longt1, double lat1, double longt2, double lat2) {
        double x, y, distance;
        x = (longt2 - longt1) * PI * R * Math.cos(((lat1 + lat2) / 2) * PI / 180) / 180;
        y = (lat2 - lat1) * PI * R / 180;
        distance = Math.hypot(x, y);
        return (int) (distance + 0.5);
    }


	/**
	 * 获取坐标距离(米)
	 *
	 * @param longt1
	 *            起始经度
	 * @param lat1
	 *            起始纬度
	 * @param longt2
	 *            目地地经度
	 * @param lat2
	 *            目的地纬度
	 * @return
	 */
	public static double getDistanceToDouble(double longt1, double lat1, double longt2, double lat2) {
		double x, y, distance;
		x = (longt2 - longt1) * PI * R * Math.cos(((lat1 + lat2) / 2) * PI / 180) / 180;
		y = (lat2 - lat1) * PI * R / 180;
		distance = Math.hypot(x, y);
		return (distance + 1);
	}


    /**
     * 将 String 经度转换成 double
     *
     * @param longitude 经度
     * @return Double 类型的经度
     */
    public static double getLongitude(String longitude) throws ServiceException {
    	if(Func.isNull(longitude) || StrUtil.isBlank(longitude)){
    		throw new ServiceException("业务异常，传入的经度不能为空！");
		}
		return Double.parseDouble(longitude);
    }

    /**
     * 将 String 纬度转换成 double
     *
     * @param latitude 纬度
     * @return Double 类型的纬度
     */
    public static double getLatitude(String latitude) throws ServiceException {
    	if(Func.isNull(latitude) || StrUtil.isBlank(latitude)){
			throw new ServiceException("业务异常，传入的纬度不能为空！");
		}
        return Double.parseDouble(latitude);
    }

    /**
     * 根据距离返回,经纬度范围 返回顺序 minLat,minLng,maxLat,maxLng
     *
     * @param lat
     * @param lon
     * @param raidus
     * @return
     */
    public static double[] getAround(double lat, double lon, int raidus) {

        try {
            Double latitude = lat;
            Double longitude = lon;

            Double degree = (24901 * 1609) / 360.0;
            double raidusMile = raidus;

            Double dpmLat = 1 / degree;
            Double radiusLat = dpmLat * raidusMile;
            Double minLat = latitude - radiusLat;
            Double maxLat = latitude + radiusLat;

            Double mpdLng = degree * Math.cos(latitude * (PI / 180));
            Double dpmLng = 1 / mpdLng;
            Double radiusLng = dpmLng * raidusMile;
            Double minLng = longitude - radiusLng;
            Double maxLng = longitude + radiusLng;

            // 格式化
            minLat = Double.parseDouble(DOUBLE_FORMAT.format(minLat));
            minLng = Double.parseDouble(DOUBLE_FORMAT.format(minLng));
            maxLat = Double.parseDouble(DOUBLE_FORMAT.format(maxLat));
            maxLng = Double.parseDouble(DOUBLE_FORMAT.format(maxLng));

            return new double[] { minLat, minLng, maxLat, maxLng };
        } catch (NumberFormatException ignored) {
        }
        return null;
    }

    /**
     * 判断是否超出规定距离范围
     *
     * @param longt1
     *            起始经度
     * @param lat1
     *            起始纬度
     * @param longt2
     *            目地地经度
     * @param lat2
     *            目的地纬度
     * @return 是否超出规定距离
     */
    public static boolean isOutOfRange(double longt1, double lat1, double longt2, double lat2) {
        int distance = getDistance(longt1, lat1, longt2, lat2);
        if(distance > STIPULATE_DISTANCE){
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }


	/**
	 * 判断是否在规定范围内
	 * @param beginLongitude 起始经度
	 * @param beginLatitude 起始纬度
	 * @param targetLongitude 目标经度
	 * @param targetLatitude 目标纬度
	 * @param targetLength 规定范围
	 * @return 是否超出： true-是，false-否
	 */
	public static boolean isInRange(double beginLongitude, double beginLatitude,
									double targetLongitude, double targetLatitude, double targetLength){
		int distance = getDistance(beginLongitude, beginLatitude,targetLongitude, targetLatitude);
		if(distance < targetLength){
			return Boolean.TRUE;
		}
		return Boolean.FALSE;
	}


	public static void main(String[] args) {
		int distance = MapUtil.getDistance(Convert.toDouble("113.399903"), Convert.toDouble("22.518611"), Convert.toDouble("113.336965"), Convert.toDouble("22.510132"));
		System.out.println(distance);
	}
}
